/**
 * 
 */
package cwinsor.com.leaf_raking;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;


/**
 * @author cwinsor
 */
public class AaaLeafRakingMeatPacker extends JPanel implements TableModelListener {

	private static final long serialVersionUID = 1L;
	protected static String newline = "\n";

	// context - rakers or supervisors
	protected JRadioButtonMenuItem buttonRkr;
	protected JRadioButtonMenuItem buttonSprv;

	// actions
	protected Action actionSetContext;

	protected Action actionPopulateFromRosterFile;
	protected Action actionPopulateFromStateFile;
	protected Action actionSaveToStateFile;
	protected Action actionImportNewSchedulePreferences;
	protected Action actionAcceptChanges;



	protected Action actionCustomerListGet;
	protected Action actionGenerateNewSchedule;
	protected Action actionCheckForParentsAsCustomers;
	protected Action actionFindDoubleDownKids;
	protected Action actionListMultiReservationCustomers;

	JScrollPane scrollPaneMain;
	JScrollPane scrollPaneSummary;

	static JTextArea bottomTextArea;
	JFileChooser fc;

	PrsnListRaker prsnListRaker;
	PrsnListSupervisor prsnListSupervisor;

	ApptList apptList;

	TableModelData tableModelDataRaker;
	TableModelData tableModelDataSupervisor;


	public AaaLeafRakingMeatPacker() {
		super(new BorderLayout());

		actionSetContext = new ActionSetContext(  "Set Context - Rakers or Supervisors",
				createNavigationIcon("Back24"),
				"Set Context - Rakers or Supervisors.", 
				new Integer(KeyEvent.VK_C));

		actionPopulateFromRosterFile = new ActionPopulateFromRosterFile(  "Populate From Roster File",
				createNavigationIcon("Back24"),
				"Populate From State File (only need to do this once per project)", 
				new Integer(KeyEvent.VK_R));

		actionPopulateFromStateFile = new ActionPopulateFromStateFile(  "Populate From State File",
				createNavigationIcon("Back24"),
				"Populate From State File.", 
				new Integer(KeyEvent.VK_S));

		actionImportNewSchedulePreferences = new ActionImportNewSchedulePreferences(  "Import New Schedule Preferences",
				createNavigationIcon("Back24"),
				"Import rakers' new schedule preferences", 
				new Integer(KeyEvent.VK_G));

		actionAcceptChanges = new ActionRakersAcceptChanges(  "Accept Add/Drop Changes",
				createNavigationIcon("Back24"),
				"Get rakers' new schedule preferences", 
				new Integer(KeyEvent.VK_A));

		actionSaveToStateFile = new ActionSaveToStateFile(  "Save To State File",
				createNavigationIcon("Back24"),
				"Save all data (rakers and supervisors) to State File", 
				new Integer(KeyEvent.VK_S));

		actionCustomerListGet = new ActionCustomerListGet("Get Customer Reservations",
				createNavigationIcon("Back24"),
				"Get customer list", 
				new Integer(KeyEvent.VK_R));

		actionGenerateNewSchedule = new ActionGenerateNewSchedule("Generate Schedule",
				createNavigationIcon("Back24"),
				"Generate a new raker/customer schedule (.csv)", 
				new Integer(KeyEvent.VK_S));

		actionCheckForParentsAsCustomers = new ActionCheckForParentCustomers("Check for parents that are customers",
				createNavigationIcon("Back24"),
				"Generate a new raker/customer schedule (.csv)", 
				new Integer(KeyEvent.VK_P));

		actionFindDoubleDownKids = new ActionFindDoubleDownKids("Find kids that are doubling down one weekend",
				createNavigationIcon("Back24"),
				"Find kids that are doubling down one weekend", 
				new Integer(KeyEvent.VK_P));

		actionListMultiReservationCustomers = new ActionListMultiReservationCustomers("List customers who have multiple reservations",
				createNavigationIcon("Back24"),
				"List customers that have multiple reservations", 
				new Integer(KeyEvent.VK_P));


		//Create a file chooser
		//fc = new JFileChooser("C:/Users/cwinsor/Documents/me/_BHRA_2014/leaf_raking/schedule_files");
		//fc = new JFileChooser("C:/Users/cwinsor/Documents/me/_BHRA_2014/leaf_raking/schedule_files_041027");
		//fc = new JFileChooser("C:/Users/cwinsor/Documents/me/_BHRA_2014/leaf_raking/schedule_files_041102");
		// fc = new JFileChooser("C:/Users/cwinsor/Documents/me/_BHRA_2014/leaf_raking/schedule_files_041103");
		fc = new JFileChooser("C:/Users/cwinsor/Documents/me/_BHRA_2014/leaf_raking/schedule_files_041111");
	}






	/*
	 * create the menu bar
	 */
	private JMenuBar createMenuBar() {

		// create menu bar
		JMenuBar menuBar;
		JMenu menu;
		JMenuItem menuItem;

		menuBar = new JMenuBar();

		//file menu
		menu = new JMenu("Menu");
		menu.setMnemonic(KeyEvent.VK_F);
		menu.getAccessibleContext().setAccessibleDescription("Menu");


		buttonRkr = new JRadioButtonMenuItem(actionSetContext);
		buttonRkr.setText("Context = Rakers");
		buttonRkr.setSelected(true);
		menu.add(buttonRkr);

		buttonSprv = new JRadioButtonMenuItem(actionSetContext);
		buttonSprv.setText("Context = Supervisors");
		buttonSprv.setSelected(false);
		menu.add(buttonSprv);

		//Group the buttons (make them exclusive)
		ButtonGroup group = new ButtonGroup();
		group.add(buttonRkr);
		group.add(buttonSprv);

		menu.addSeparator();

		menuItem = new JMenuItem(actionPopulateFromRosterFile);
		menu.add(menuItem);

		menuItem = new JMenuItem(actionPopulateFromStateFile);
		menu.add(menuItem);

		menuItem = new JMenuItem(actionSaveToStateFile);
		menu.add(menuItem);

		menu.addSeparator();

		menuItem = new JMenuItem(actionImportNewSchedulePreferences);
		menu.add(menuItem);

		menuItem = new JMenuItem(actionAcceptChanges);
		menu.add(menuItem);

		menu.addSeparator();

		menuItem = new JMenuItem(actionFindDoubleDownKids);
		menu.add(menuItem);

		menu.addSeparator();

		menuItem = new JMenuItem(actionCustomerListGet);
		menu.add(menuItem);

		menuItem = new JMenuItem(actionListMultiReservationCustomers);
		menu.add(menuItem);

		menuItem = new JMenuItem(actionCheckForParentsAsCustomers);
		menu.add(menuItem);

		menuBar.add(menu);

		menuItem = new JMenuItem(actionGenerateNewSchedule);
		menu.add(menuItem);

		menuBar.add(menu);

		return  menuBar;
	}


	/*
	 * create initial content pane
	 * here we only add the (scrolled) text area at bottom for messages
	 * separate methods are used to add (scrolled) tables (raker or supervisor, data and summary)
	 */
	private Container contentPaneAddMessageArea() {

		//Create a scrolled text area.
		bottomTextArea = new JTextArea(6, 500);
		bottomTextArea.setEditable(false);

		JScrollPane scrollPaneEnd = new JScrollPane(bottomTextArea);
		this.add(scrollPaneEnd, BorderLayout.PAGE_END);

		return this;	
	}


	private void contentPaneSetViewRakers() {

		// remove current content panes
		if (scrollPaneMain != null)
			this.remove(scrollPaneMain);
		if (scrollPaneSummary != null)
			this.remove(scrollPaneSummary);

		// sanity check - make sure something is available to display
		if ((prsnListRaker == null) || (prsnListRaker.getCount() == 0)) {
			displayResult("nothing to display (no rakers loaded)");
		}
		else {
			// make the main table
			tableModelDataRaker = new TableModelDataRaker(prsnListRaker, tableModelDataSupervisor);
			final JTableData jTableDataRaker = new JTableData(tableModelDataRaker );


			// make the summary table
			TableModelSummary tableModelSummaryRaker = new TableModelSummaryRaker();
			final JTable jTableSummaryRaker = new JTable(tableModelSummaryRaker);


			// summary table has access to main table for calculation purposes
			tableModelSummaryRaker.setReferenceToMainTable(tableModelDataRaker);

			// main table manages column widths of summary table...
			jTableDataRaker.manageSummaryTableColumnEvents(jTableSummaryRaker);

			// set column widths on main table
			tableModelDataRaker.setColumnWidths(jTableDataRaker);

			///// ZONA - work in progress - register THIS for TableChanged events in raker data table
			jTableDataRaker.getModel().addTableModelListener(this);

			jTableDataRaker.setup();
			//	jTableSummaryRaker.setup();

			// create scroll panes - with data and summary in them
			scrollPaneMain = new JScrollPane(jTableDataRaker);
			scrollPaneSummary = new JScrollPane(jTableSummaryRaker);
			scrollPaneMain.setPreferredSize(new Dimension(450, 600));
			// scrollPaneSummary.setPreferredSize(new Dimension(450, 300));
			this.add(scrollPaneMain, BorderLayout.PAGE_START);
			this.add(scrollPaneSummary, BorderLayout.CENTER);




		}

		// revalidate and repaint
		this.validate();
		this.repaint();
	}


	private void contentPaneSetViewSupervisors() {

		// remove current content panes
		if (scrollPaneMain != null)
			this.remove(scrollPaneMain);
		if (scrollPaneSummary != null)
			this.remove(scrollPaneSummary);

		// sanity check - make sure something is available to display
		if ((prsnListSupervisor == null) || (prsnListSupervisor.getCount() == 0)) {
			displayResult("nothing to display (no supervisors loaded)");
		}
		else {
			// make the main table
			tableModelDataSupervisor = new TableModelDataSupervisor(prsnListSupervisor, tableModelDataRaker);
			final JTableData jTableDataSupervisor = new JTableData(tableModelDataSupervisor );
			jTableDataSupervisor.setup();

			// make the summary table
			TableModelSummary tableModelSummarySupervisor = new TableModelSummarySupervisor();
			final JTable jTableSummarySupervisor = new JTable(tableModelSummarySupervisor);
			jTableDataSupervisor.setup();

			// summary table has access to main table for calculation purposes
			tableModelSummarySupervisor.setReferenceToMainTable(tableModelDataSupervisor);

			// main table manages column widths of summary table...
			jTableDataSupervisor.manageSummaryTableColumnEvents(jTableSummarySupervisor);

			// set column widths on main table
			tableModelDataSupervisor.setColumnWidths(jTableDataSupervisor);

			// create scroll panes - with data and summary in them
			scrollPaneMain = new JScrollPane(jTableDataSupervisor);
			scrollPaneSummary = new JScrollPane(jTableSummarySupervisor);
			scrollPaneMain.setPreferredSize(new Dimension(450, 600));
			// scrollPaneSummary.setPreferredSize(new Dimension(450, 300));
			this.add(scrollPaneMain, BorderLayout.NORTH);
			this.add(scrollPaneSummary, BorderLayout.CENTER);
		}

		// revalidate and repaint
		this.validate();
		this.repaint();
	}

	public class ActionPopulateFromRosterFile extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionPopulateFromRosterFile(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			int returnVal = fc.showOpenDialog(AaaLeafRakingMeatPacker.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File file = fc.getSelectedFile();
				FileType fileType = new FileTypeRoster();

				if (buttonRkr.isSelected()) {
					displayResult("Populating rakers from: " + file.getName() + "  (" + file.getPath() + ")");
					prsnListRaker = new PrsnListRaker();
					prsnListRaker.populateFromFile(fileType, file);
					displayResult("Populated " + prsnListRaker.getCount());
					contentPaneSetViewRakers();
				} 
				if (buttonSprv.isSelected()) {
					displayResult("Populating supervisors from: " + file.getName() + "  (" + file.getPath() + ")");
					prsnListSupervisor= new PrsnListSupervisor();
					prsnListSupervisor.populateFromFile(fileType, file);
					displayResult("Populated " + prsnListSupervisor.getCount());
					contentPaneSetViewSupervisors();
				}
			} else {
				displayResult("Command cancelled by user.");
			}
		}
	}

	public class ActionPopulateFromStateFile extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionPopulateFromStateFile(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			int returnVal = fc.showOpenDialog(AaaLeafRakingMeatPacker.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File file = fc.getSelectedFile();
				FileType fileType = new FileTypeState();

				if (buttonRkr.isSelected()) {
					displayResult("Getting rakers from: " + file.getName() + "  (" + file.getPath() + ")");
					prsnListRaker = new PrsnListRaker();
					prsnListRaker.populateFromFile(fileType, file);
					displayResult("Populated " + prsnListRaker.getCount());
					contentPaneSetViewRakers();
				} 
				if (buttonSprv.isSelected()) {
					displayResult("Getting supervisors from: " + file.getName() + "  (" + file.getPath() + ")");
					prsnListSupervisor= new PrsnListSupervisor();
					prsnListSupervisor.populateFromFile(fileType, file);
					displayResult("Populated " + prsnListSupervisor.getCount());
					contentPaneSetViewSupervisors();
				}
			} else {
				displayResult("Command cancelled by user.");
			}
		}
	}

	public class ActionSaveToStateFile extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionSaveToStateFile(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			//			if (buttonRkr.isSelected()) {
			//				fc.setName("state_raker_000");
			//			}
			//			if (buttonSprv.isSelected()) {
			//				fc.setName("state_supervisor_000");	
			//			}
			int returnVal = fc.showOpenDialog(AaaLeafRakingMeatPacker.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				// open a writer
				File fileName = fc.getSelectedFile();
				PrintWriter writer = null;
				try {
					writer = new PrintWriter(fileName);
				} catch (FileNotFoundException e1) {
					e1.printStackTrace();
					Msg.fatal(dM + ": caught an exception");
				}
				// create one of my file format objects
				FileType fileType = new FileTypeState();

				if (buttonRkr.isSelected()) {
					displayResult("Saving raker file: " + fileName.getName() + "  (" + fileName.getPath() + ")");
					prsnListRaker.writeToFile(fileType, writer);
				}
				else if (buttonSprv.isSelected()) {
					displayResult("Saving supervisor file: " + fileName.getName() + "  (" + fileName.getPath() + ")");
					prsnListSupervisor.writeToFile(fileType, writer);
				} else {
					displayResult("Command cancelled by user.");
				}
				System.out.println("main: ----- closing the file");
				writer.close();
			}
		}
	}


	public class ActionImportNewSchedulePreferences extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionImportNewSchedulePreferences(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			int returnVal = fc.showOpenDialog(AaaLeafRakingMeatPacker.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File file = fc.getSelectedFile();

				if (buttonRkr.isSelected()) {
					displayResult("Getting raker availability updates from: " + file.getName() + "  (" + file.getPath() + ")");
					FileType fileType = new FileTypeSchedulePreferencesRaker();
					prsnListRaker.applySchedulePreferencesFromFile(fileType, file);
				}
				else if (buttonSprv.isSelected()) {
					displayResult("Getting supervisor availability updates from: " + file.getName() + "  (" + file.getPath() + ")");
					FileType fileType = new FileTypeSchedulePreferencesSupervisor();
					prsnListSupervisor.applySchedulePreferencesFromFile(fileType, file);
				}
			} else {
				displayResult("Command cancelled by user.");
			}
		}
	}

	public class ActionRakersAcceptChanges extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionRakersAcceptChanges(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			if (buttonRkr.isSelected()) {
				prsnListRaker.acceptAddDrops();
				displayResult("Accepted appointment Add/Drops (rakers)");
			}
			if (buttonSprv.isSelected()) {
				prsnListSupervisor.acceptAddDrops();
				displayResult("Accepted appointment Add/Drops (supervisors)");
			}
		}
	}

	public class ActionSetContext extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionSetContext(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			if (buttonRkr.isSelected()) {
				displayResult("Context = Rakers");
				contentPaneSetViewRakers();
			}
			if (buttonSprv.isSelected()) {
				displayResult("Context = Supervisors");
				contentPaneSetViewSupervisors();
			}
		}
	}



	public class ActionCustomerListGet extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionCustomerListGet(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			int returnVal = fc.showOpenDialog(AaaLeafRakingMeatPacker.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File file = fc.getSelectedFile();
				displayResult("Getting: " + file.getName() + "  (" + file.getPath() + ")");
				apptList = new ApptList();
				apptList.readCsvFile(file);
			} else {
				displayResult("Command cancelled by user.");
			}
		}
	}

	public class ActionGenerateNewSchedule extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionGenerateNewSchedule(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			int returnVal = fc.showOpenDialog(AaaLeafRakingMeatPacker.this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File file = fc.getSelectedFile();
				displayResult("Generating: " + file.getName() + "  (" + file.getPath() + ")");
				generateNewScheduleCsv(file);
			} else {
				displayResult("Command cancelled by user.");
			}
		}
	}


	public class ActionCheckForParentCustomers extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionCheckForParentCustomers(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			checkForParentsAsCustomers();
		}
	}


	public class ActionFindDoubleDownKids extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionFindDoubleDownKids(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			findDoubleDownKids();
		}
	}


	public class ActionListMultiReservationCustomers extends AbstractAction {
		private static final long serialVersionUID = 1L;
		public ActionListMultiReservationCustomers(String text, ImageIcon icon,
				String desc, Integer mnemonic) {
			super(text, icon);
			putValue(SHORT_DESCRIPTION, desc);
			putValue(MNEMONIC_KEY, mnemonic);
		}
		public void actionPerformed(ActionEvent e) {
			listMultiReservationCustomers();
		}
	}


	/*
	 * check for parents that are customers
	 */
	public void help() {

		/*
There is a context button - rakers vs supervisors.

Populate From Roster File - depending on the context (raker or supervisor) it will populate either the raker names, or names of the parents. 
So you need to poulate from roster file TWICE - once for rakers, once for parents.
There are 2 parents for each kid so the quantity reflects that.  

Populate from State File - a state file has the names plus add/drop info.  You can save to state, or populate from state.

		 */
	}

	/*
	 * check for parents that are customers
	 */
	public void listMultiReservationCustomers() {
		int count = 0;

		Msg.note(dM + ": list multi-reservation customers");

		for (Appointment a1 : apptList.getList()) {
			String addr1 = a1.getAddress();

			count = 0;
			for (Appointment a2 : apptList.getList()) {
				String addr2 = a2.getAddress();

				if (addr1.equals(addr2)) {
					count++;
				}
			}

			// if we found an address that shows up more than once...
			if (count > 1) {

				for (Appointment a2 : apptList.getList()) {
					String addr2 = a2.getAddress();

					if (addr1.equals(addr2)) {
						Msg.note(dM + " " 
								+ a2.getName() + " " 
								+ a2.getDay().name() 
								+ " " + a2.getShiftInfo()
								+ " " + a2.getTeam());
					}
				}
			}
		}
	}


	/*
	 * check for parents that are customers
	 */
	public void checkForParentsAsCustomers() {

		Msg.note(dM + ": check for parents as customers");

		for (Appointment a : apptList.getList()) {
			String addr = a.getAddress();
			addr = addr.trim();
			if (addr.length()>=6) {
				addr = addr.substring(0, 6);
			} else {
				addr = "xxxxxx";
			}

			for (Person p : prsnListRaker.getPersonList()) {
				String addr2 = p.getStreet();
				addr2 = addr2.trim();
				if (addr2.length()>=6) {
					addr2 = addr2.substring(0,6);
				} else {
					addr2 = "yyyyyy";
				}
				if (addr.equalsIgnoreCase(addr2)) {
					Msg.note(dM + "-------------------------------");
					Msg.note(dM + "appointment " + a.getName() + " " + a.getAddress());
					Msg.note(dM + "rower       " + p.getFirstName() + " " + p.getLastName() + " " + p.getStreet());
				}
			}
		}
		Msg.note(dM + "--------- done ----------------");
	}


	/*
	 * find kids that are double-downs (away one weekend, need to rake twice on one of the weekends)
	 */
	public void findDoubleDownKids() {

		Msg.note(dM + ": find double-down kids");

		Msg.note(dM + ": ------ NOT AVAILABLE NOV1/2 -----");
		for (Person p : prsnListRaker.getPersonList()) {
			if (
					p.getCurrentAvailability(WorkShift.NOV_1_AM).equals(-2) &&
					p.getCurrentAvailability(WorkShift.NOV_1_PM).equals(-2) &&
					p.getCurrentAvailability(WorkShift.NOV_2_AM).equals(-2) &&
					p.getCurrentAvailability(WorkShift.NOV_2_PM).equals(-2)) {
				Msg.note(dM + "rower       " + p.getFirstName() + " " + p.getLastName());
			}
		}
		Msg.note(dM + ": ------ NOT AVAILABLE NOV8/9 -----");
		for (Person p : prsnListRaker.getPersonList()) {
			if (
					p.getCurrentAvailability(WorkShift.NOV_8_AM).equals(-2) &&
					p.getCurrentAvailability(WorkShift.NOV_8_PM).equals(-2) &&
					p.getCurrentAvailability(WorkShift.NOV_9_AM).equals(-2) &&
					p.getCurrentAvailability(WorkShift.NOV_9_PM).equals(-2)) {
				Msg.note(dM + "rower       " + p.getFirstName() + " " + p.getLastName());
			}
		}
		Msg.note(dM + "--------- done ----------------");
	}




	/*
	 * generate a new schedule (.csv file)
	 */
	public void generateNewScheduleCsv(File outfile) {

		Msg.note(dM + ": generate a schedule");

		if ((prsnListRaker == null) ||
				(prsnListSupervisor == null)) {
			Msg.note(dM + ": ERROR - cannot generate schedule - have not loaded Rakers or Supervisors");
		}


		PrintWriter writer = null;
		try {
			writer = new PrintWriter(outfile);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			Msg.note(dM + ": ----------------------------------------------------");
			Msg.note(dM + ": caught an exception - FileNotFound (probably in use)");
			Msg.note(dM + ": command is ignored - you may proceed                ");
			Msg.note(dM + ": ----------------------------------------------------");
			return;
		}

		FileType fT = new FileTypeAppointmentSchedule();

		// create a header - date and time
		// DateFormat dateFormat = new SimpleDateFormat("MM/dd HH:mm");
		//get current date time with Date()
		// Date date = new Date();
		//	System.out.println(dateFormat.format(date));

		fT.writeToFile(writer,"BHRA Raking Fundraiser - Schedule for November 8 and November 9\n");
		fT.writeToFile(writer,"Rev B");
		fT.writeToFile(writer,"\n\n");
		fT.writeToFile(writer,"SUPERVISORS:\n");
		fT.writeToFile(writer,"MORNING SUPERVISORS: get equipment at Blanchard (Boxborough) Memorial School parking lot (8AM)\n");
		fT.writeToFile(writer,"AFTERNOON SUPERVISORS: get equipment from the AM team at their last customer\n");
		fT.writeToFile(writer,"AFTERNOON SUPERVISORS: RETURN EQUIPMENT to Bromfield School when you are done\n");
		fT.writeToFile(writer,"\n");
		fT.writeToFile(writer,"IN CASE OF A NO-SHOW - CALL THE RAKER CELL/HOME - IT IS ON SCHEDULE BELOW\n");
		fT.writeToFile(writer,"\n");
		fT.writeToFile(writer,"EQUIPMENT/SCHEDULE PROBLEMS:\n");
		fT.writeToFile(writer,"   Saturday -> Chris Winsor 978-621-2724\n");
		fT.writeToFile(writer,"\n");
		fT.writeToFile(writer,"PARENTS:\n");
		fT.writeToFile(writer,"Bring you rower to the first customer site where you will meet your supervisor and team.  Plan to arrive 15 minutes before the scheduled time\n");
		fT.writeToFile(writer,"Pick up your rower at the team's final customer site at the scheduled end time");
		fT.writeToFile(writer,"The supervisor will transport the rowers between customer sites");
		fT.writeToFile(writer,"\n\n");
		fT.writeToFile(writer,"PRICING:\n");
		fT.writeToFile(writer,"Generic prices are shown below.  It is based on the time reserved\n");
		fT.writeToFile(writer,"Anything in the NOTES relating to pricing takes precidence for that customer\n");
		fT.writeToFile(writer,"If there is disagreement between you and customer - go with what the customer says and make a note\n");
		fT.writeToFile(writer,"  1   HOUR  = $120\n");
		fT.writeToFile(writer,"  1.5 HOURS = $180\n");
		fT.writeToFile(writer,"  2   HOURS = $220\n");
		fT.writeToFile(writer,"  2.5 HOURS (BACK-TO-BACK 1-HOUR TIMESLOTS) = $260\n");
		fT.writeToFile(writer,"\n");


		// for a specific set of days
		List<Day> dayList = new ArrayList<Day>();
		//dayList.add(Day.NOV_1);
		//dayList.add(Day.NOV_2);
		//dayList.add(Day.NOV_8);
		//dayList.add(Day.NOV_9);
		dayList.add(Day.NOV_15);
		dayList.add(Day.NOV_16);
		for (Day day : dayList) {

			System.out.println("main: --------------------------");
			System.out.println("main: --------------------------" + day.name());
			System.out.println("main: --------------------------");



			fT.writeToFile(writer, "\n");
			fT.writeToFile(writer, "---------- " + day.name() + " ----------");



			// for each team number
			for (TeamNumber teamNumber : TeamNumber.TEAMS_NO_U) {

				fT.writeToFile(writer, "\n");

				// for am/pm shifts
				for (AmPm amPm : AmPm.asList()) {

					System.out.println("main: --------------------------" + day.name() + " " + teamNumber.name() + " " + amPm.name());
					fT.writeToFile(writer, "\n");
					fT.writeToFile(writer, " * " + day.name() + " " + teamNumber.name() + " " + amPm.name() + "\n");

					WorkShift workShift = WorkShift.fromDayAmPm(day, amPm);

					// identify the subset of supervisors (hopefully==1) for the day/shift/team in question
					PrsnList supervisorsThisShift = prsnListSupervisor.getPersonsDayShiftTeam(workShift,teamNumber);
					for (Person p : supervisorsThisShift.getPersonList()) {
						System.out.println("main: ----------- " + p.getType() + " " + p.getFirstName() + " " + p.getLastName());
					}
					supervisorsThisShift.writeToFile(fT, writer);

					// write to the file
					PrsnList rakersThisShift = prsnListRaker.getPersonsDayShiftTeam(workShift,teamNumber);
					for (Person p : rakersThisShift.getPersonList()) {
						System.out.println("main: ----------- " + p.getType() + " " + p.getFirstName() + " " + p.getLastName());
					}
					rakersThisShift.writeToFile(fT,  writer);

					// customers
					ApptList customersThisShift = apptList.getCustomersDayShiftTeam(workShift, teamNumber);
					customersThisShift.sort();
					System.out.println("main: ----------- " + "CUSTOMERS = " + customersThisShift.count());
					fT.writeToFile(writer, customersThisShift.toCsvString());
				}
			}
		}
		System.out.println("main: ----- closing this file");
		writer.close();
	}



	/** Returns an ImageIcon, or null if the path was invalid. */
	protected static ImageIcon createNavigationIcon(String imageName) {
		return null;
		/*
		String imgLocation = "toolbarButtonGraphics/navigation/"
				+ imageName
				+ ".gif";

		java.net.URL imageURL = ActionDemo.class.getResource(imgLocation);

		if (imageURL == null) {
			System.err.println("Resource not found: "
					+ imgLocation);
			return null;
		} else {
			return new ImageIcon(imageURL);
		}
		 */
	}

	public static void displayResult(String message) {
		String s = (message
				+ newline);
		bottomTextArea.append(s);
	}


	/*
	 * static - construct the frame
	 */
	private static void createAndShowGUI(){

		//Create and set up the frame
		JFrame frame = new JFrame("BHRA Leaf Raking");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		AaaLeafRakingMeatPacker leafRakingJPanel = new AaaLeafRakingMeatPacker();
		frame.setJMenuBar(leafRakingJPanel.createMenuBar());
		frame.setContentPane(leafRakingJPanel.contentPaneAddMessageArea());

		//Display the window.
		frame.setSize(1500, 900);
		frame.setVisible(true);
	}

	/*
	 * main entry point - thread safe
	 */
	public static void main(String[] args){
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGUI();
			}
		});
	}


	@Override
	public void tableChanged(TableModelEvent e) {
		Msg.note(dM + ": ZONA TEMP - received TableModelEvent!");
	}


	// debug message
	String dM = this.getClass().getSimpleName();
}
